﻿Namespace Load

    ''' <summary>
    ''' ページコマンドファクトリー
    ''' </summary>
    ''' <remarks></remarks>
    Public Class PageCommandFactory

        ''' <summary>
        ''' ソート条件
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Property SortProperties As String() = Nothing

        ''' <summary>
        ''' ページサイズ
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Property PageSize As Integer = 20

        Private _pageno As Integer?
        ''' <summary>
        ''' ページ番号
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Property PageNo As Integer?
            Get
                Return If(_pageno Is Nothing OrElse _pageno <= 1, 1, _pageno)
            End Get
            Set(ByVal value As Integer?)
                _pageno = value
            End Set
        End Property

        ''' <summary>
        ''' 全件数取得コマンドの生成
        ''' </summary>
        ''' <param name="cmd">オリジナルコマンド</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overridable Function CreateCountCommand(ByVal cmd As IDbCommand) As IDbCommand
            Dim c As IDbCommand = cmd.Connection.CreateCommand
            c.Transaction = cmd.Transaction

            c.CommandText = String.Format("SELECT COUNT(*) FROM ({0}) Q", cmd.CommandText)

            For Each item As IDbDataParameter In cmd.Parameters
                Dim p As IDbDataParameter = c.CreateParameter
                p.ParameterName = item.ParameterName
                p.Value = item.Value
                c.Parameters.Add(p)
            Next

            Return c
        End Function

        ''' <summary>
        ''' ページ取得コマンドの生成
        ''' </summary>
        ''' <param name="cmd">オリジナルコマンド</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overridable Function CreatePageCommand(def As TableAlias, ByVal cmd As System.Data.IDbCommand) As System.Data.IDbCommand
            Dim c As IDbCommand = cmd.Connection.CreateCommand
            c.Transaction = cmd.Transaction

            'ソート条件の作成
            Dim sortText As String = String.Empty
            Dim addSort As Action(Of String) = Sub(s)
                                                   If String.IsNullOrEmpty(sortText) = False Then sortText &= ", "
                                                   sortText &= s
                                               End Sub

            For Each item As String In Me.SortProperties
                Dim s As String = item
                addSort.Invoke((From el In def.ColumnAliases Where el.Column.PropertyInfo.Name = s Select el.Index).First)
            Next

            c.CommandText = String.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY {1}) AS ROW_NO, Q.* FROM ({0}) Q) Q WHERE Q.ROW_NO BETWEEN @ROW_START AND (@ROW_START + @ROW_TAKE - 1)", cmd.CommandText, sortText)

            For Each item As IDbDataParameter In cmd.Parameters
                Dim p As IDbDataParameter = c.CreateParameter
                p.ParameterName = item.ParameterName
                p.Value = item.Value
                c.Parameters.Add(p)
            Next

            Dim start As Integer = Me.PageSize * (Me.PageNo - 1) + 1
            Dim take As Integer = Me.PageSize
            c.Parameters.Add(CreateParameter(c, "ROW_START", start))
            c.Parameters.Add(CreateParameter(c, "ROW_TAKE", take))

            Return c
        End Function

        ''' <summary>
        ''' パラメーターを生成します
        ''' </summary>
        ''' <param name="cmd"></param>
        ''' <param name="name"></param>
        ''' <param name="val"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Shared Function CreateParameter(ByVal cmd As IDbCommand, ByVal name As String, ByVal val As Object) As IDbDataParameter
            Dim prm As IDbDataParameter = cmd.CreateParameter
            prm.ParameterName = name
            prm.Value = val
            Return prm
        End Function

    End Class

End Namespace